﻿/*
 * Operation Map
operation	parameters	exact?	result	description
val	1	yes	v	Defines a guide value from some other value.
sum	3	yes	v + P1 ­ P2	Used for addition and subtraction.
product	3	rounds	v × P1 / P2	Used for multiplication and division.
mid	2	rounds to zero	(v + P1) / 2	Average.
abs	1	yes	abs(v)	Absolute value.
min	2	yes	min(v, P1)	The lesser of v and P1.
max	2	yes	max(v, P1)	The greater of v and P1.
if	3	yes	v > 0 ? P1 : P2	Condition testing.
mod	3	no		Modulus (etc.)
atan2	2	no	atan2(P1, v)	Polar arithmetic – result is in degrees·216. (fd units.)
sin	2	no	v × sin(P1)	Sine, argument is in degrees·216. (fd units.)
cos	2	no	v × cos(P1)	Cosine, argument is in degrees·216. (fd units.)
cosatan2	3	no	v × cos(atan2(P2, P1)	Preserves full accuracy in intermediate calculation.
sinatan2	3	no	v × sin(atan2(P2, P1)	
sqrt	1	no	sqrt(v)	Result is positive, rounds down.
sumangle	3	yes	v + P1×216 - P2×216	v is an existing angle (scaled by 216),
				P1 and P2 are numbers of degrees.
ellipse	3	no		
tan	2	no	v × tan(P1)	Tangent, argument is in degrees·216. (fd units.)

 
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace vmlModel.Entities
{
   // public enum Operationv {val,sum,product,mid,abs,min,max,ifx,mod,atan2,sin,cos,cosatan2,sinatan2,sqrt,sumangle,ellipse,tan}
    public class vmlFormula : vmlObject
    {
        public vmlPathShapeBase rPath { get; set; }

        public string EQN { get { return (vmlObjElement.Attribute("eqn") != null) ? vmlObjElement.Attribute("eqn").Value : ""; } }
        public string Operation { get { return EQN.Split(' ')[0]; } }
        public double V { get {
            string v = EQN.Split(' ')[1];
            if (v == "height" || v == "width")
            {
                if (rPath.GetType() == typeof(vmlShapeType))
                {
                    ((vmlShapeType)rPath).NeedToAdjustFormulas = true;
                }
            }
            return rPath.FormulaCalculateString(EQN.Split(' ')[1]); } 
        }
        public double P1 { get { return rPath.FormulaCalculateString(EQN.Split(' ')[2]); } }
        public double P2 { get { return rPath.FormulaCalculateString(EQN.Split(' ')[3]); } }
 
        public double Result
        {
            get {
                double _result = 0;
                switch (Operation.ToLower())
                {
                    case "val":
                        return V;
                    case "sum":
                        return V + P1 - P2;
                    case "product":
                    case "prod":
                        return V * P1 / P2;
                    case "mid":
                        return (V + P1) / 2;
                    case "abs":
                        return Math.Abs(V);
                    case "min":
                        return Math.Min(V, P1);
                    case "max":
                        return  Math.Max(V, P1);;
                    case "if":
                        return (V > 0) ? P1 : P2;
                    case "mod":
                        return V;
                    case "atan2":
                        return Math.Atan2(P1, V); 
                    case "sin":
                        return V * Math.Sign(P1);
                    case "cos":
                        return V * Math.Cos(P1);
                    case "cosatan2":
                        return V * Math.Cos(Math.Atan2(P2, P1));
                    case "sinatan2":
                        return V * Math.Sign(Math.Atan2(P2, P1));
                    case "sqrt":
                        return Math.Sqrt(V);
                    case "sumangle":
                        return V + P1*216 - P2*216;
                    case "ellipse":
                        break;
                    case "tan":
                       return  V * Math.Tan(P1);
                    default:
                        break;
                }
                return _result;
            }
        }
        public vmlFormula()
        {

        }
        public vmlFormula(vmlPathShapeBase ParentShp, XElement _vmlObjElement)
            : base(_vmlObjElement)
        {
            rPath = ParentShp;
        }
    }
}
